const {
	resolve
} = require('path')
const path = require('path')
const htmlwebpackplugin = require('html-webpack-plugin')
const minicssextractplugin = require('mini-css-extract-plugin') //提取css
const optimizecssassetswebpackplugin = require('optimize-css-assets-webpack-plugin') //压缩css
process.env.NODE_ENV = "production" //设置当前环境变量 不设置默认是生产环境   production   development
module.exports = {
	entry: ['./src/index.js', './index.html'], //主流仍是单页面
	// entry: { //多入口 加别名 模块分割
	// 	main: './src/index.js',
	// 	test: './src/index2.js'
	// },
	output: {
		//filename: 'js/index.js',
		filename: 'js/[name].[contenthash:3].js',
		path: resolve(__dirname, 'dist')
	},
	module: {
		//可在rules里写oneOf包起来配置项来优化打包速度，不过注意不要出现多个规则对应一种类型文件
		rules: [{
				/*
				1.基本js兼容三件套  babel-loader @babel/core  @babel/preset-env
				2.万能js兼容   @babel/polyfill  (需要在需要兼容的js里import导入使用) 缺点：体积过大
				3.按需引入js兼容  core-js
				*/
				test: /\.js$/,
				exclude: /node_modules/,
				loader: 'babel-loader',
				enforce: 'pre', //优先执行
				options: {
					// presets: ['@babel/preset-env'] 基本js兼容写法&万能js兼容写法
					//以下为按需引入写法,此时不需要在引入@babel/polyfill 
					presets: [
						[
							'@babel/preset-env',
							{
								useBuiltIns: 'usage',
								corejs: {
									version: 3 //3.19.1
								},
								//按需兼容 value是版本号 代表兼容该版本及以上
								targets: {
									chrome: '60',
									firefox: '60',
									ie: '9',
									safari: '10',
									edge: '17'
								}
							}
						]
					],
					cacheDirectory: true, //再次构建时对babel进行缓存
					/*
					 缓存  hash 时间戳 版本号  都可以让文件重新请求不走缓存
					 hash 改动共享一个hash
					 chunkhash 模块各自改动产生的hash
					 contenthash  不用文件类型改动产生的hash
					 
					 用法示例
					 在output文件名后面添加 => .[contenthash:10](在结尾文件类型之前插入)
					*/
				}
			},
			// {
			// 	由于版本变迁  下列配置已无效
			// 	//注意下载eslint四件套
			// 	test: /\.js$/,
			// 	exclude: /node_modules/,
			// 	loader: 'eslint-loader',
			// 	options: {					
			// 		// 自动修复 出现的错误  或者 在错误上一行加上注释 eslint-disable-next-line 也可避开检查
			// 		// 最常见的是引入 .eslintrc.js配置文件				
			// 		//fix: true
			// 	}
			// },
			{
				test: /\.css$/, // exclude是!test
				use: [ //从数组的右边开始执行
					minicssextractplugin.loader, //'style-loader', 把字符串转成style挂载在页面上
					{
						loader: 'css-loader',
						options: {
							esModule: false,
							importLoaders: 1
						}
					}
				]
			}, {
				test: /\.scss$/,
				use: [minicssextractplugin.loader,
					{
						loader: 'css-loader',
						options: {
							esModule: false,
							importLoaders: 1
						}
					},
					{
						loader: 'postcss-loader',
						options: {
							postcssOptions: {
								plugins: ["postcss-preset-env"] //最新写法
							}
						}
					},
					'sass-loader'
				]
			}, {
				test: /\.(jpg|png|gif)$/,
				loader: 'url-loader', //需要下载file-loader配合
				options: {
					outputPath: 'img/', // dist下img  最好不要手动设置publicPath让其自适应路径方便引入资源			
					limit: 5 * 1024, // 图片小于 5kb,会被 base64处理，本地形式处理				
					esModule: false, //关闭url-loader的es6模块化，使用commonjs解析			
					name: '[name][hash:6].[ext]' // [hash:6]取图片的hash的前6位 [ext]取文件原来的扩展名
				},
				type: 'javascript/auto', //在webpack5中使用旧版功能
			}, {
				//把html里的url引入的图片按照上述↑方式处理，不过要多一句 esModule: false,
				test: /\.html$/,
				loader: 'html-loader'
			}, {
				test: /\.(woff2|woff|ttf)$/,
				loader: 'file-loader',
				options: {
					outputPath: 'iconfont/', // dist下img
					name: '[name][hash:6].[ext]',
					esModule: false
				},
				type: 'javascript/auto'
			}
		]
	},
	plugins: [
		new htmlwebpackplugin({
			//会自动在模板处引入css和js
			template: './index.html',
			minify: {
				collapseWhitespace: true, //移除空格并压缩
				removeComments: true //移除注释
			}
		}),
		new minicssextractplugin({
			filename: 'css/index.css' //最终编译为一个css文件
		}),
		new optimizecssassetswebpackplugin()
	],
	devServer: {
		//启动服务指令  npx webpack-dev-server
		static: {
			directory: path.join(__dirname, 'index.html'),
		},
		compress: true, //gzip压缩
		open: true, //自动打开浏览器
		port: 3000,
		hot: true, //启动HMR 热模块加载
		/*
		css 可以触发hmr 因为style-loader实现了 （生产环境还是需要用style-loader）
		js  默认不能触发hmr  一般用于非入口文件的替换 需要在入口文件写能被hmr支持的监听代码
		html 也是触发不了hmr 而且还会导致无法热更新了 解决方案：将html也当做入口文件 => entry: ['./src/index.js', './index.html']
		*/
	},
	/*
	以下值可以组合
	 source-map               映射后的代码与出口js文件同级的.map文件里   提供错误代码的信息和源代码位置
	 inline-source-map        映射后的代码写入出口js文件里(构建速度快)   提供错误代码的信息和源代码位置
	 hidden-source-map        映射后的代码与出口js文件同级的.map文件里   只提供构建后代码的错误信息和位置
	 eval-source-map          映射后的代码写入出口js文件里(每个模块都有对应的source-map)   提供错误代码的信息和源代码位置(位置是哈希值)
	 nosources-source-map     映射后的代码与出口js文件同级的.map文件里   只提供错误信息和位置不提供任何代码
	 cheap-source-map         映射后的代码与出口js文件同级的.map文件里   提供错误代码的信息和源代码位置(只能精确到行不能定位列)
	 cheap-module-source-map  映射后的代码与出口js文件同级的.map文件里   提供错误代码的信息和源代码位置(只能精确到行不能定位列)
	*/
	devtool: 'source-map', //默认与出口js文件同级
	mode: 'production', //development
	optimization: { //优化打包  模块化  单独打包成单个js
		splitChunks: {
			chunks: 'all'
		}
	},
	// performance: {
	// 	hints: false //关闭提示入口文件大于244kb,未来技术成熟了要学习压缩分割去优化代码
	// }
	//mode: 'development' 生产环境下会自动压缩js

	/*
	 tree shaking
	 当你使用es6语法和production环境后会自动开启  来去除无用的代码	 
	 在pakeages.json文件里写入以下代码可规避样式文件被当做无用代码剔除
	 "sideEffects":["*.css","*.scss"] 
	 
	 PWA 一开始有网后来断网也可以继续访问的技术（就和现在手机应用一样） service worker
	 
	 thread-loader 和 HappyPack 可以实现多进程打包
	 
	 externals 就是防止cdn进来的资源也被打包
	 
	 dll  一种将第三方库只打包一次后引入且后续不再重复打包的技术(会产生manifest.JSON文件)
	*/
}

